package dao

import (
	"errors"
	"gorm.io/gorm"
	"gotham-plan-manage/internal/infra/database/mysql/plan/po"
	"gotham-plan-manage/pkg/dateutils"
	"time"
)

/*
   @author:zhongyang
   @date:2023/4/4
   @description:待办表数据库操作
*/

type TaskDao struct {
}

func NewTaskDao() *TaskDao {
	return &TaskDao{}
}

func (p *TaskDao) DeleteByPlanId(db *gorm.DB, taskPO *po.TaskPO) error {
	return db.Where("plan_id = ?", taskPO.PlanId).Delete(&taskPO).Error
}

func (p *TaskDao) FindByPlanId(db *gorm.DB, planId string) ([]*po.TaskPO, error) {
	var res []*po.TaskPO
	err := db.Where("plan_id = ?", planId).Find(&res).Error
	if err != nil {
		return nil, err
	}
	return res, nil
}

func (p *TaskDao) GetOneByPlanIdAndDate(db *gorm.DB, planId string, date string) (*po.TaskPO, error) {
	var res *po.TaskPO
	err := db.Where("plan_id = ? and execute_date = ?", planId, date).First(&res).Error
	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		return nil, err
	}
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return nil, nil
	}
	return res, nil
}

func (p *TaskDao) GetOne(db *gorm.DB, taskId string) (*po.TaskPO, error) {
	var res *po.TaskPO
	err := db.Where("todo_task_id = ?", taskId).First(&res).Error
	if err != nil {
		return nil, err
	}
	return res, nil
}

func (p *TaskDao) Create(db *gorm.DB, taskPO *po.TaskPO) error {
	return db.Create(&taskPO).Error
}

func (p *TaskDao) Delete(db *gorm.DB, taskId string) error {
	return db.Where("todo_task_id = ?", taskId).Delete(&po.TaskPO{}).Error
}

func (p *TaskDao) FindTaskTotalByUserId(db *gorm.DB, userId string) (int64, error) {
	var total int64
	err := db.Model(&po.TaskPO{}).Where("user_id = ?", userId).First(&total).Error
	if err != nil {
		return 0, err
	}
	return total, nil
}

func (p *TaskDao) FindPageByPlanId(db *gorm.DB, userId string, planId string, page int, pageSize int) ([]*po.TaskPO, int64, error) {
	var total int64
	limit := pageSize
	offset := pageSize * (page - 1)
	db = db.Model(&po.TaskPO{}).Select("todo_task_id,plan_id,user_id,execute_date").Where("user_id = ? and plan_id = ?", userId, planId)
	err := db.Count(&total).Error
	if err != nil {
		return nil, 0, err
	}
	var res []*po.TaskPO
	err = db.Order("execute_date desc").Offset(offset).Limit(limit).Find(&res).Error
	if err != nil {
		return nil, 0, err
	}
	return res, total, nil
}

func (p *TaskDao) Save(db *gorm.DB, taskPO *po.TaskPO) error {
	return db.Save(&taskPO).Error
}

func (p *TaskDao) FindOngoingTasksByPlanIds(db *gorm.DB, planIds []string, scope string) ([]*po.TaskPO, error) {
	var todoTasks []*po.TaskPO
	tx := db.Where("plan_id in ?", planIds)
	switch scope {
	case "today":
		tx = tx.Where("execute_date = ?", time.Now().Format("2006-01-02"))
	case "week":
		// 获取本周开始结束时间
		startDate, endDate := dateutils.WeekIntervalTime(0)
		tx = tx.Where("execute_date >= ? and execute_date <= ?", startDate, endDate)
	case "all":
	default:
	}
	err := tx.Find(&todoTasks).Error
	if err != nil {
		return nil, err
	}
	return todoTasks, nil
}

func (p *TaskDao) FindByPlanIdAndDate(db *gorm.DB, planId string, executeDate string) ([]*po.TaskPO, error) {
	var res []*po.TaskPO
	err := db.Where("plan_id = ? and execute_date = ?", planId, executeDate).Find(&res).Error
	if err != nil {
		return nil, err
	}
	return res, nil
}

func (p *TaskDao) FindAllByPlanId(db *gorm.DB, planID string) ([]*po.TaskPO, error) {
	var res []*po.TaskPO
	err := db.Where("plan_id = ?", planID).Order("execute_date desc").Find(&res).Error
	if err != nil {
		return nil, err
	}
	return res, nil
}

func (p *TaskDao) FindAllByPlanIdAndDateRange(db *gorm.DB, id string, startDate string, endDate string) ([]*po.TaskPO, error) {
	var res []*po.TaskPO
	err := db.Where("plan_id = ? and execute_date between ? and ?", id, startDate, endDate).Find(&res).Error
	if err != nil {
		return nil, err
	}
	return res, nil
}
